---
title: Getting started with LiveStore + React
description: How to use LiveStore with React on the web.
sidebar:
  label: React web
  order: 1
---

import { Steps, Tabs, TabItem, Code } from '@astrojs/starlight/components';
import { makeCreate, versionNpmSuffix } from '../../../data/data.ts'
import { MIN_NODE_VERSION } from '@local/shared'
import viteConfigCode from '../../../../../examples/web-todomvc-sync-cf/vite.config.js?raw'
import SchemaSnippet from '../../_assets/code/getting-started/react-web/livestore/schema.ts?snippet'
import WorkerSnippet from '../../_assets/code/getting-started/react-web/livestore.worker.ts?snippet'
import RootSnippet from '../../_assets/code/getting-started/react-web/Root.tsx?snippet'
import HeaderSnippet from '../../_assets/code/getting-started/react-web/Header.tsx?snippet'
import MainSectionSnippet from '../../_assets/code/getting-started/react-web/MainSection.tsx?snippet'

export const CODE = {
  viteConfig: viteConfigCode,
}

export const SNIPPETS = {
  schema: SchemaSnippet,
  root: RootSnippet,
  header: HeaderSnippet,
  mainSection: MainSectionSnippet,
  worker: WorkerSnippet,
}

{/* We're adjusting the package to use the dev version on the dev branch */}
export const manualInstallDepsStr = [
  '@livestore/livestore' + versionNpmSuffix,
  '@livestore/wa-sqlite' + versionNpmSuffix,
  '@livestore/adapter-web' + versionNpmSuffix,
  '@livestore/react' + versionNpmSuffix,
  '@livestore/peer-deps' + versionNpmSuffix,
  '@livestore/sync-cf' + versionNpmSuffix,
  '@livestore/devtools-vite' + versionNpmSuffix,
].join(' ')

## Prerequisites

- Recommended: Bun 1.2 or higher
- Node.js {MIN_NODE_VERSION} or higher

### Option A: Quick start

For a quick start, we recommend using our template app following the steps below.

For existing projects, see [Existing project setup](#existing-project-setup).

<Steps>

1. **Set up project from template**

   <Tabs syncKey="package-manager">
     <TabItem label="bun">
       <Code code={makeCreate('web-todomvc-sync-cf', 'bunx')} lang="sh" />
     </TabItem>
     <TabItem label="pnpm">
       <Code code={makeCreate('web-todomvc-sync-cf', 'pnpm dlx')} lang="sh" />
     </TabItem>
     <TabItem label="npm">
       <Code code={makeCreate('web-todomvc-sync-cf', 'npx')} lang="sh" />
     </TabItem>
   </Tabs>

   Replace `livestore-app` with your desired app name.

2. **Install dependencies**

   It's strongly recommended to use `bun` or `pnpm` for the simplest and most reliable dependency setup (see [note on package management](/misc/package-management) for more details).

   <Tabs syncKey="package-manager">
     <TabItem label="bun">
       <Code code="bun install" lang="sh" />
     </TabItem>
     <TabItem label="pnpm">
       <Code code="pnpm install" lang="sh" />
     </TabItem>
     <TabItem label="npm">
       <Code code="npm install" lang="sh" />
     </TabItem>
   </Tabs>

   Pro tip: You can use [direnv](https://direnv.net/) to manage environment variables.

3. **Run dev environment**

   <Tabs syncKey="package-manager">
     <TabItem label="bun">
       <Code code="bun dev" lang="sh" />
     </TabItem>
     <TabItem label="pnpm">
       <Code code="pnpm dev" lang="sh" />
     </TabItem>
     <TabItem label="npm">
       <Code code="npm run dev" lang="sh" />
     </TabItem>
   </Tabs>

4. **Open browser**

   Open `http://localhost:60000` in your browser.

   You can also open the devtools by going to `http://localhost:60000/_livestore`.

</Steps>

### Option B: Existing project setup \{#existing-project-setup\}

<Steps>

1. **Install dependencies**

   <Tabs syncKey="package-manager">
     <TabItem label="bun">
       <Code code={'bun install ' + manualInstallDepsStr} lang="sh" />
     </TabItem>
     <TabItem label="pnpm">
       <Code code={'pnpm add ' + manualInstallDepsStr} lang="sh" />
     </TabItem>
     <TabItem label="npm">
       <Code code={'npm install ' + manualInstallDepsStr} lang="sh" />
     </TabItem>
   </Tabs>

2. **Update Vite config**

   Add the following code to your `vite.config.js` file:

   <Code code={viteConfigCode} lang="js" title="vite.config.js" />
</Steps>

## Define your schema

Create a file named `schema.ts` inside the `src/livestore` folder. This file defines your LiveStore schema consisting of your app's event definitions (describing how data changes), derived state (i.e. SQLite tables), and materializers (how state is derived from events).

Here's an example schema:

<SNIPPETS.schema />

## Create the LiveStore worker

Create a file named `livestore.worker.ts` inside the `src` folder. This file will contain the LiveStore web worker. When importing this file, make sure to add the `?worker` extension to the import path to ensure that Vite treats it as a worker file.

<SNIPPETS.worker />

## Add the LiveStore provider

To make the LiveStore available throughout your app, wrap your app's root component with the `LiveStoreProvider` component from `@livestore/react`. This provider manages your app's data store, loading, and error states.

Here's an example:

<SNIPPETS.root />

### Commit events

After wrapping your app with the `LiveStoreProvider`, you can use the `useStore` hook from any component to commit events.

Here's an example:

<SNIPPETS.header />

## Queries

To retrieve data from the database, first define a query using `queryDb` from `@livestore/livestore`. Then, execute the query with the `useQuery` hook from `@livestore/react`.

Consider abstracting queries into a separate file to keep your code organized, though you can also define them directly within components if preferred.

Here's an example:

<SNIPPETS.mainSection />
